package com.du.quant.service;

import com.du.quant.constant.AnalyzeStock;
import com.du.quant.dto.HistoryDataDTO;
import com.du.quant.dto.StockAnalysisDTO;
import com.du.quant.entity.StockHistory;
import com.du.quant.mapper.StockHistoryMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class StockDataService {

    @Value("${stock.api.sina-history}")
    private String sinaHistoryUrl;

    @Value("${stock.api.qq-realtime}")
    private String qqRealtimeUrl;

    @Autowired
    private StockHistoryMapper stockHistoryMapper;

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 获取股票实时数据
     */
    public StockHistory getRealTimeStockData(String stockCode) {
        try {
            String qqCode = convertToQQFormat(stockCode);
            String url = qqRealtimeUrl + qqCode;

            String response = sendHttpGetRequest(url);
            return parseQQResponse(response, stockCode);

        } catch (Exception e) {
            log.error("获取股票实时数据失败: {}", stockCode, e);
            return null;
        }
    }

    /**
     * 获取股票历史数据
     */
    @Transactional
    public List<HistoryDataDTO> getStockHistoryData(String stockCode, int days) {
        List<HistoryDataDTO> result = new ArrayList<>();

        try {
            // 先尝试从数据库获取
//            LocalDate startDate = LocalDate.now().minusDays(days);
//            List<StockHistory> dbData = stockHistoryMapper.selectByStockCodeAndDate(stockCode, startDate);
//
//            if (!dbData.isEmpty()) {
//                // 转换数据库数据为DTO
//                for (StockHistory history : dbData) {
//                    HistoryDataDTO dto = new HistoryDataDTO();
//                    dto.setDate(history.getTradeDate().format(dateFormatter));
//                    dto.setOpen(history.getOpenPrice());
//                    dto.setClose(history.getClosePrice());
//                    dto.setHigh(history.getHighPrice());
//                    dto.setLow(history.getLowPrice());
//                    dto.setVolume(history.getVolume());
//                    result.add(dto);
//                }
//
//                if (result.size() >= days * 0.6) { // 如果数据库数据足够
//                    return result;
//                }
//            }

            // 从API获取数据
            List<HistoryDataDTO> apiData = fetchFromSinaAPI(stockCode, days);
            if (apiData != null && !apiData.isEmpty()) {
                apiData = apiData.stream()
                        .sorted(Comparator.comparing(obj -> {
                            String dateStr = obj.getDate();
                            return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                        }))
                        .collect(Collectors.toList());
                // 保存到数据库
//                saveHistoryData(stockCode, apiData);
                return apiData;
            }

        } catch (Exception e) {
            log.error("获取股票历史数据失败: {}", stockCode, e);
        }

        return result;
    }

    private List<HistoryDataDTO> fetchFromSinaAPI(String stockCode, int days) {
        try {
            // 新浪历史数据API参数
            String symbol = stockCode.startsWith("6") ? "sh" + stockCode : "sz" + stockCode;
            String url = String.format("%s?symbol=%s&scale=240&ma=no&datalen=%d",
                    sinaHistoryUrl, symbol, days);

            String response = sendHttpGetRequest(url);
            return parseSinaHistoryResponse(response);

        } catch (Exception e) {
            log.error("从新浪API获取历史数据失败: {}", stockCode, e);
            return null;
        }
    }

    private List<HistoryDataDTO> parseSinaHistoryResponse(String response) {
        List<HistoryDataDTO> result = new ArrayList<>();

        try {
            // 新浪返回的是JSON数组
            JsonNode jsonArray = objectMapper.readTree(response);

            for (JsonNode item : jsonArray) {
                HistoryDataDTO dto = new HistoryDataDTO();
                dto.setDate(item.path("day").asText());
                dto.setOpen(new BigDecimal(item.path("open").asText()));
                dto.setClose(new BigDecimal(item.path("close").asText()));
                dto.setHigh(new BigDecimal(item.path("high").asText()));
                dto.setLow(new BigDecimal(item.path("low").asText()));
                dto.setVolume(item.path("volume").asLong());
                result.add(dto);
            }
        } catch (Exception e) {
            log.error("解析新浪历史数据失败", e);
        }

        return result;
    }

    /**
     * 解析腾讯股票历史数据
     * 在StockDataService.java的parseQQResponse方法中添加changeRate计算
     * <p>
     * 字段解析（按顺序）：
     * 0: 未知（可能是数据版本或类型）
     * 1: 股票名称
     * 2: 股票代码
     * 3: 当前价格
     * 4: 昨日收盘价
     * 5: 今日开盘价
     * 6: 成交量（手）
     * 7: 外盘（手）
     * 8: 内盘（手）
     * 9: 未知
     * 10: 成交额（万元）
     * 11: 未知
     * 12: 未知
     * </p>
     * @param response
     * @param stockCode
     * @return
     */
    private StockHistory parseQQResponse(String response, String stockCode) {
        try {
            // 腾讯返回格式：v_sz000001="51~平安银行~000001~12.85~12.80~12.81~1214177~155773~1058404~~1256.81~~
            String[] fields = response.split("~");

            if (fields.length >= 5) {
                StockHistory history = new StockHistory();
                StockAnalysisDTO analysisDTO = AnalyzeStock.analyzeResult.get();
                analysisDTO.setStockCode(stockCode);
                analysisDTO.setStockName(fields[1]);

                history.setStockCode(stockCode);

                // 成交量
                analysisDTO.setTurnoverNum(fields[36]);
                // 成交额
                analysisDTO.setTurnoverMoney(fields[37]);

                BigDecimal closePrice = new BigDecimal(fields[3]);
                BigDecimal prevClosePrice = new BigDecimal(fields[4]); // 假设第4个字段是昨日收盘价

                history.setClosePrice(closePrice);
                history.setOpenPrice(prevClosePrice);
                history.setTradeDate(LocalDate.now());

                // 计算涨跌幅
                if (prevClosePrice.compareTo(BigDecimal.ZERO) != 0) {
                    BigDecimal changeRate = closePrice.subtract(prevClosePrice)
                            .divide(prevClosePrice, 4, RoundingMode.HALF_UP)
                            .multiply(new BigDecimal("100"));
                    history.setChangeRate(changeRate);
                } else {
                    history.setChangeRate(BigDecimal.ZERO);
                }

                return history;
            }
        } catch (Exception e) {
            log.error("解析腾讯实时数据失败", e);
        }

        return null;
    }

    private String convertToQQFormat(String stockCode) {
        if (stockCode.startsWith("6")) {
            return "sh" + stockCode;
        } else {
            return "sz" + stockCode;
        }
    }

    private String sendHttpGetRequest(String url) throws Exception {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        }
    }

    @Transactional
    public void saveHistoryData(String stockCode, List<HistoryDataDTO> historyData) {
        // 删除旧数据
        stockHistoryMapper.deleteByStockCode(stockCode);
        for (HistoryDataDTO dto : historyData) {
            try {
                StockHistory history = new StockHistory();
                history.setStockCode(stockCode);
                history.setTradeDate(LocalDate.parse(dto.getDate(), dateFormatter));
                history.setOpenPrice(dto.getOpen());
                history.setClosePrice(dto.getClose());
                history.setHighPrice(dto.getHigh());
                history.setLowPrice(dto.getLow());
                history.setVolume(dto.getVolume());

                stockHistoryMapper.insert(history);
            } catch (Exception e) {
                log.warn("保存历史数据失败: {}", dto.getDate(), e);
            }
        }
    }
}